package com.jt.resource.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * @author tang
 * @data 2021/9/26
 * @apiNode
 * 定义一个AOP设置中的切面对象
 * 思考:切面对象的构成
 * 1) 切入点(执行拓展业务逻辑的入门) : @Pointcut
 * 2) 通知方法(封装拓展业务逻辑) : @Around...
 */
@Slf4j
@Aspect
@Component
public class LogAspect {
    /**
     * @Pointcut中定义切入点表达式
     * 表达式中要描述在哪些地方定义切入点
     * 表达式的定义有多种写法,在这里采用注解方式的表达式
     */
    @Pointcut("@annotation(com.jt.resource.annotation.RequiredLog)")  //细腻度表达式  使用此注解描述的方法切入点方法
    //@Pointcut("bean(resourceController)")  //粗度表达式  指定bean
    //@Pointcut("within(com.jt..resource.controller)")  //指定包的指定类
    public void doLog(){}

    /**
     * 在执行的切入点方法上执行@Around注解描述的方法  即doLog()
     * @param jp 连接点(封装了要执行的执行链信息,包括目标方法信息)
     * @return  目标方法的返回值
     * @throws  Throwable
     */
    @Around("doLog()")  //当只有一个切入点方法可以使用方法2
    //@Around("@annotation(com.jt.resource.annotation.RequiredLog)")  //方法2
    public Object doAround(ProceedingJoinPoint jp) throws Throwable {
        log.info("Around Before {}", LocalDateTime.now());
        Object result = jp.proceed();//执行我们的目标执行链(包含切面,目标方法)
        log.info("Around After {}", LocalDateTime.now());
        return result;
    }
}
